#define _CRT_SECURE_NO_WARNINGS s


#include <iostream>
#include "node.h"
Expr::Expr(int type)
	:op(nullptr), type((Token::TokenType)type) {

}
Expr::Expr()
	: op(nullptr), type((Token::TokenType)type) {

}
Expr::Expr(Token* op) : op(op), type((Token::TokenType)type) {

}

Expr* Expr::reduce() {
	return this;
}

Expr* Expr::gen() {
	return this;
}
// #pragma warning(disable : 4996)
std::string Expr::toString() {
	std::string s;
	char buffer[16] = { 0 };
	if (type == Token::NUM) {
		NumToken* n = (NumToken*)op;
		_itoa(n->value, buffer, 10);
		s.append(buffer);
	}
	else {
		Word* w = (Word*)op;
		s.append(w->lexeme);
	}
	return s;
}


Op::Op()
	: Expr(Token::TokenType::ELSE) {

}
Op::Op(Token *op) : Expr(op) {}

Expr* Op::reduce() {
	Expr* x = gen();
	Temp* t = new Temp();
	std::cout << t->toString() + "=" + x->toString() << std::endl;
	return t;
}

Temp::Temp()
	: Expr(Token::TokenType::TEMP), number('0'+count) {
	++count;
}
int Temp::count = 0;
std::string Temp::toString() {
	std::string s;
	s.push_back('t');
	s.push_back(number);
	return s;
}

Arith::Arith(Token* op, Expr  *e1, Expr *e2)
	: Op(op), expr1(e1), expr2(e2) {
}

Expr* Arith::gen() {
	Expr* f1 = expr1->reduce();
	Expr* f2 = expr2->reduce();

	return new Arith(op, f1, f2);
}

std::string Arith::toString() {
	std::string s;
	s.append(expr1->toString());
	s.append(op->toString());
	s.append(expr2->toString());
	return s;
}

Stmt::Stmt(Token *op) : op(op) {

}

Stmt* Stmt::null = new Stmt(nullptr);


std::string Stmt::toString() {
	std::string s;
	if (op) {
		s.append(op->toString());
	}
	return s;
}

void Stmt::gen() {

}

Assign::Assign(Expr* id, Expr* eval) :Stmt(nullptr), id(id), eval(eval) {

}

std::string Assign::toString() {
	std::string s;
	Expr* g = eval->gen();
	s.append(id->toString());
	s.push_back('=');
	s.append(g->toString());
	return s;
}

void Assign::gen() {
	std::cout << toString() << std::endl;
}

Seq::Seq(Stmt* s1, Stmt* s2) : Stmt(nullptr), s1(s1), s2(s2) {

}

void Seq::gen() {
	s2->gen();
	s1->gen();
}